]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
grabHelper: Rework grabbing code to properly handle stacking
authorJasper St. Pierre <jstpierre@mecheye.net>
Sat, 15 Sep 2012 05:38:40 +0000 (02:38 -0300)
committerJasper St. Pierre <jstpierre@mecheye.net>
Sat, 15 Sep 2012 13:32:31 +0000 (10:32 -0300)
When Dan Winship wrote the GrabHelper code originally, it didn't
handle a grab stack. I wrote the grab stack code hastily when landed
the message tray, not understanding all of the code that was involved
here.

Fix it so that we properly do the operations for each type of grab
when we first need to, and not sometimes when the first grab is taken.

https://bugzilla.gnome.org/show_bug.cgi?id=683546

js/ui/grabHelper.js

index 7120043b828da4534d3dd333bf2123beb8ad7b92..fee72c51e502c3542a97cccbf492effc6dffb07a 100644 (file)
@@ -156,19 +156,14 @@ const GrabHelper = new Lang.Class({
         if (this.isActorGrabbed(params.actor))
             return true;
 
-        if (this._grabFocusCount == 0 && this._modalCount == 0) {
-            if (!this._fullGrab(hadFocus, params.modal, params.grabFocus))
-                return false;
-        }
-
         params.savedFocus = focus;
         this._grabStack.push(params);
 
         if (params.modal)
-            this._modalCount++;
+            this._takeModalGrab(hadFocus);
 
         if (params.grabFocus)
-            this._grabFocusCount++;
+            this._takeFocusGrab(hadFocus);
 
         if (hadFocus || params.grabFocus)
             _navigateActor(newFocus);
@@ -176,34 +171,89 @@ const GrabHelper = new Lang.Class({
         return true;
     },
 
-    _fullGrab: function(hadFocus, modal, grabFocus) {
-        let metaDisplay = global.screen.get_display();
+    _takeModalGrab: function(hadFocus) {
+        let firstGrab = (this._modalCount == 0);
+        this._modalCount++;
+        if (!firstGrab)
+            return;
+
+        if (!Main.pushModal(this._owner))
+            return;
+
+        this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
+        this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent));
+    },
+
+    _releaseModalGrab: function() {
+        this._modalCount--;
+        if (this._modalCount > 0)
+            return;
+
+        if (this._capturedEventId > 0) {
+            global.stage.disconnect(this._capturedEventId);
+            this._capturedEventId = 0;
+        }
 
-        if (modal) {
-            if (!Main.pushModal(this._owner))
-                return false;
+        if (this._eventId > 0) {
+            global.stage.disconnect(this._eventId);
+            this._eventId = 0;
         }
 
-        this._grabbedFromKeynav = hadFocus;
+        Main.popModal(this._owner);
+        global.sync_pointer();
+    },
+
+    _takeFocusGrab: function() {
+        let firstGrab = (this._grabFocusCount == 0);
+        this._grabFocusCount++;
+        if (!firstGrab)
+            return;
+
+        let metaDisplay = global.screen.get_display();
+
         this._preGrabInputMode = global.stage_input_mode;
-        this._prevFocusedWindow = null;
+        this._prevFocusedWindow = metaDisplay.focus_window;
 
-        if (grabFocus) {
-            this._prevFocusedWindow = metaDisplay.focus_window;
-            if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE ||
-                this._preGrabInputMode == Shell.StageInputMode.NORMAL) {
-                global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
-            }
+        if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE ||
+            this._preGrabInputMode == Shell.StageInputMode.NORMAL) {
+            global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
         }
 
-        if (modal || grabFocus) {
-            this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
-            this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent));
-            this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
-            this._focusWindowChangedId = metaDisplay.connect('notify::focus-window', Lang.bind(this, this._focusWindowChanged));
+        this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
+        this._focusWindowChangedId = metaDisplay.connect('notify::focus-window', Lang.bind(this, this._focusWindowChanged));
+    },
+
+    _releaseFocusGrab: function() {
+        this._grabFocusCount--;
+        if (this._grabFocusCount > 0)
+            return;
+
+        if (this._keyFocusNotifyId > 0) {
+            global.stage.disconnect(this._keyFocusNotifyId);
+            this._keyFocusNotifyId = 0;
         }
 
-        return true;
+        if (!this._focusWindowChanged > 0) {
+            let metaDisplay = global.screen.get_display();
+            metaDisplay.disconnect(this._focusWindowChangedId);
+            this._focusWindowChangedId = 0;
+        }
+
+        let prePopInputMode = global.stage_input_mode;
+
+        if (this._grabbedFromKeynav) {
+            if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED &&
+                prePopInputMode != Shell.StageInputMode.FULLSCREEN)
+                global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
+        }
+
+        if (this._prevFocusedWindow) {
+            let metaDisplay = global.screen.get_display();
+            if (!metaDisplay.focus_window) {
+                metaDisplay.set_input_focus_window(this._prevFocusedWindow,
+                                                   false, global.get_current_time());
+            }
+        }
     },
 
     // ignoreRelease:
@@ -230,12 +280,14 @@ const GrabHelper = new Lang.Class({
         if (grabStackIndex < 0)
             return;
 
+        let focus = global.stage.key_focus;
+        let hadFocus = focus && this._isWithinGrabbedActor(focus);
+
         let poppedGrabs = this._grabStack.slice(grabStackIndex);
         // "Pop" all newly ungrabbed actors off the grab stack
         // by truncating the array.
         this._grabStack.length = grabStackIndex;
 
-        let wasModal = this._modalCount > 0;
         for (let i = poppedGrabs.length - 1; i >= 0; i--) {
             let poppedGrab = poppedGrabs[i];
 
@@ -243,65 +295,15 @@ const GrabHelper = new Lang.Class({
                 poppedGrab.onUngrab();
 
             if (poppedGrab.modal)
-                this._modalCount--;
+                this._releaseModalGrab();
 
             if (poppedGrab.grabFocus)
-                this._grabFocusCount--;
+                this._releaseFocusGrab();
         }
 
-        let focus = global.stage.key_focus;
-        let hadFocus = focus && this._isWithinGrabbedActor(focus);
-
-        if (this._grabFocusCount == 0 && this._modalCount == 0)
-            this._fullUngrab(wasModal);
-
-        let poppedGrab = poppedGrabs[0];
-
-        if (hadFocus)
+        if (hadFocus) {
+            let poppedGrab = poppedGrabs[0];
             _navigateActor(poppedGrab.savedFocus);
-    },
-
-    _fullUngrab: function(wasModal) {
-        if (this._capturedEventId > 0) {
-            global.stage.disconnect(this._capturedEventId);
-            this._capturedEventId = 0;
-        }
-
-        if (this._eventId > 0) {
-            global.stage.disconnect(this._eventId);
-            this._eventId = 0;
-        }
-
-        if (this._keyFocusNotifyId > 0) {
-            global.stage.disconnect(this._keyFocusNotifyId);
-            this._keyFocusNotifyId = 0;
-        }
-
-        if (!this._focusWindowChanged > 0) {
-            let metaDisplay = global.screen.get_display();
-            metaDisplay.disconnect(this._focusWindowChangedId);
-            this._focusWindowChangedId = 0;
-        }
-
-        let prePopInputMode = global.stage_input_mode;
-
-        if (wasModal) {
-            Main.popModal(this._owner);
-            global.sync_pointer();
-        }
-
-        if (this._grabbedFromKeynav) {
-            if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED &&
-                prePopInputMode != Shell.StageInputMode.FULLSCREEN)
-                global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
-        }
-
-        if (this._prevFocusedWindow) {
-            let metaDisplay = global.screen.get_display();
-            if (!metaDisplay.focus_window) {
-                metaDisplay.set_input_focus_window(this._prevFocusedWindow,
-                                                   false, global.get_current_time());
-            }
         }
     },